const { ccclass, property } = cc._decorator;
import n from "./NodePool"
@ccclass
export default class ScrollViewCtrl extends cc.Component {
    @property(cc.Prefab)
    itemPrefab: cc.Prefab = null;

    public scrollView = null;
    public content = null;
    public view = null;
    public layout = null;
    public itemName = null;
    public mat4 = null;
    public isInit = null;
    public data = null;
    public callbackList = null;
    public extData = null;
    public firstX = null;
    public firstY = null;
    public itemCache = null;
    public itemBuffer = null;
    public _tmpV2 = null;
    public viewRect = null;
    public bindIndexList;

    public start() {
        this.initOnce();
    };
    public initOnce() {
        this.bindIndexList = {};
        this.scrollView = this.node.getComponent(cc.ScrollView);
        this.content = this.scrollView.content;
        this.view = this.content.parent;
        this.layout = this.content.getComponent(cc.Layout);
        this.itemName = this.itemPrefab.name;
        this.mat4 = cc.mat4();
        this.initOnce() { };
    };
    public onDestroy() {
        this.content.off(cc.Node.EventType.POSITION_CHANGED, this.scrollEvent, this);
        this.recycle();
    };
    public registerScrollEvent(e, t) {
        if (e.name) {
            var a = this.node.getComponent(cc.ScrollView), o = new cc.Component.EventHandler();
            o.target = t.node;
            o.component = cc.js.getClassName(t);
            o.handler = e.name;
            var i = a.scrollEvents.length;
            a.scrollEvents[i] = o;
        }
    };
    public init(e, t) {
        var a = this;
        this.initOnce();
        if (Array.isArray(e)) {
            t = t || {};
            this.isInit = true;
            this.data = e;
            this.callbackList = [];
            this.extData = t.extData;
            t.onChanged && this.onItemChanged(t.onChanged);
            this.layout.enabled = false;
            this.scrollView.stopAutoScroll();
            n.hasPool(this.itemName) || n.initPool(this.itemPrefab);
            var o = this.itemPrefab.data, i = this.layout.paddingLeft, r = this.layout.paddingRight, l = this.layout.paddingTop, s = this.layout.paddingBottom, c = this.layout.spacingX, u = this.layout.spacingY, p = o.x, d = o.y;
            if (this.scrollView.horizontal) {
                p = -o.width / 2;
                p -= i;
            }
            if (this.scrollView.vertical) {
                d = -o.height / 2;
                d -= l;
            }
            this.firstX = p;
            this.firstY = d;
            this.itemCache = [];
            this.itemBuffer = this.itemBuffer || [];
            this.itemBuffer.forEach((e) => {
                e.index = -1;
                e.item.x = -9999999;
                e.item.y = -9999999;
                e.item.opacity = 0;
            });
            var h = (e) => {
                a.itemCache[e] = a.itemCache[e] || {};
                a.itemCache[e].x = p;
                a.itemCache[e].y = d;
                a.itemCache[e].width = o.width;
                a.itemCache[e].height = o.height;
                a.itemCache[e].scaleX = o.scaleX;
                a.itemCache[e].scaleY = o.scaleY;
                a.itemCache[e].visible = false;
            };
            h(0);
            for (var f = 1; f < this.data.length; f++) {
                h(f);
                this.scrollView.horizontal && (this.itemCache[f].x = this.itemCache[f - 1].x - (this.itemCache[f - 1].width / 2 + this.itemCache[f].width / 2 + c));
                this.scrollView.vertical && (this.itemCache[f].y = this.itemCache[f - 1].y - (this.itemCache[f - 1].height / 2 + this.itemCache[f].height / 2 + u));
            }
            var g = this.itemCache[this.itemCache.length - 1];
            this.scrollView.horizontal && (this.content.width = Math.abs(g.x + g.width / 2 + r));
            this.scrollView.vertical && (this.content.height = Math.abs(g.y - g.height / 2 - s));
            this.content.on(cc.Node.EventType.POSITION_CHANGED, this.scrollEvent, this);
            this.scheduleOnce(this.updateListView);
        } else console.error("传进来的数据不为数组！");
    };
    public updateItemView(e, t) {
        var a = this.getScript(e);
        if (a && a.setData) {
            a.setData(this.data[t], t, this.extData);
            a.updateView && a.updateView();
        }
    };
    public getItem() {
        var e = n.getNode(this.itemName);
        e.x = this.firstX;
        e.y = this.firstY;
        var t = {
            item: e,
            index: -1
        };
        this.itemBuffer.push(t);
        e.on(cc.Node.EventType.SIZE_CHANGED, this.onItemSizeChanged.bind(this, e), this);
        e.on(cc.Node.EventType.SCALE_CHANGED, this.onItemSizeChanged.bind(this, e), this);
        return t;
    };
    public scrollEvent() {
        this.content && this.isInit && this.updateListView();
    };
    public updateListView() {
        var e = this;
        if (this.itemCache) {
            for (var t = (t, a) => {
                t.index = a;
                t.item.x = e.itemCache[a].x;
                t.item.y = e.itemCache[a].y;
                t.item.scaleX = e.itemCache[a].scaleX;
                t.item.scaleY = e.itemCache[a].scaleY;
                t.item.opacity = 255;
                e.scrollView.horizontal && (t.item.width = e.itemCache[a].width);
                e.scrollView.vertical && (t.item.height = e.itemCache[a].height);
                t.item.parent = e.content;
                e.updateItemView(t.item, a);
            }, a = 0; a < this.itemCache.length; a++) {
                var o = this.itemCache[a], i = this.isItemInView(a), r = this.itemBuffer.find((e) => {
                    return e.index == a;
                });
                if (i) {
                    this.bindIndexList[a] && (r = this.itemBuffer.find((e) => {
                        return e.bindIndex == a;
                    }));
                    r || (r = (r = this.itemBuffer.find((e) => {
                        return -1 == e.index && null == e.bindIndex;
                    })) || this.getItem());
                    r.index != a && t(r, a);
                } else if (r) {
                    r.index = -1;
                    r.item.x = -9999999;
                    r.item.y = -9999999;
                    r.item.opacity = 0;
                }
                o.visible != i && this.runItemChangedCallback(a, i);
                o.visible = i;
            }
            this.itemBuffer.sort(function (e, t) {
                return e.index < 0 || t.index < 0 ? 1 : e.index - t.index;
            });
            for (a = 0; a < this.itemBuffer.length; a++) this.itemBuffer[a].item.setSiblingIndex(a);
        }
    };
    public isItemInView(e) {
        this._tmpV2 = this._tmpV2 || cc.v2(0, 0);
        this.view.getWorldMatrix(this.mat4);
        var t = this.mat4.m[0], a = this.mat4.m[12], o = this.mat4.m[13], i = this.view.width * t, r = this.view.height * t, n = this.view.convertToWorldSpaceAR(cc.Vec2.ZERO, this._tmpV2);
        this.viewRect && 1 == t && this.viewRect.x + i / 2 == a && this.viewRect.y + r / 2 == o || (this.viewRect = new cc.Rect(n.x - i / 2, n.y - r / 2, i, r));
        var l = this.itemCache[e], s = this.content.convertToWorldSpaceAR(cc.v2(l.x, l.y)), c = l.width * l.scaleX, u = l.height * l.scaleY, p = new cc.Rect(s.x - c / 2, s.y - u / 2, c, u);
        return this.viewRect.intersects(p);
    };
    public onItemSizeChanged(e) {
        if (this.itemCache) {
            var t = this.itemBuffer.find(function (t) {
                return t.item == e;
            });
            if (t && t.index >= 0) {
                var a = this.itemCache[t.index];
                if (this.scrollView.horizontal && a.width == e.width && a.scaleX == e.scaleX) return;
                if (this.scrollView.vertical && a.height == e.height && a.scaleY == e.scaleY) return;
                a.width = e.width;
                a.scaleX = e.scaleX;
                a.height = e.height;
                a.scaleY = e.scaleY;
                this.updateBuffer();
                this.scheduleOnce(this.updateListView);
            }
        }
    };
    public setItemProperty(e, t, a) {
        if (this.itemCache && this.itemBuffer) {
            var o = this.itemBuffer.find(function (t) {
                return t.index == e;
            });
            o ? o.item[t] = a : this.itemCache[e][t] = a;
            this.updateBuffer();
            this.scheduleOnce(this.updateListView);
        }
    };
    public updateBuffer() {
        var e = this, t = this.itemCache[this.itemCache.length - 1];
        if (this.scrollView.vertical) {
            this.itemCache[0].y = -this.itemCache[0].height / 2 - this.layout.paddingTop;
            1 != this.itemCache[0].scaleY && (this.itemCache[0].y = -Math.abs(this.itemCache[0].scaleY * this.itemCache[0].height) / 2 - this.layout.paddingTop);
            this.itemBuffer.find(function (t) {
                0 == t.index && (t.item.y = e.itemCache[0].y);
            });
            for (var a = 1; a < this.data.length; a++) {
                var o = this.itemCache[a - 1], i = this.itemCache[a], r = o.height, n = i.height;
                1 != o.scaleY && (r = Math.abs(o.scaleY * o.height));
                1 != i.scaleY && (n = Math.abs(i.scaleY * i.height));
                i.y = o.y - (r / 2 + n / 2 + this.layout.spacingY);
                this.itemBuffer.find((e) => {
                    e.index == a && (e.item.y = i.y);
                });
            }
            var l = t.height / 2;
            1 != t.scaleY && (l = Math.abs(t.scaleY * t.height) / 2);
            this.content.height = Math.abs(t.y - l - this.layout.paddingBottom);
        }
    };
    public scrollToItem(e, t, a) {
        if (this.itemCache) {
            e < 0 && (e = 0);
            e >= this.itemCache.length && (e = this.itemCache.length - 1);
            var o = this.itemCache[e];
            if (o) {
                a = a || {};
                t = t || 0;
                if (this.scrollView) {
                    var i;
                    if (a.customTween) { } else {
                        i = -(o.y + Math.abs(o.height * o.scaleY) / 2);
                        this.scrollView.scrollToOffset(cc.v2(0, i), t);
                    }
                }
            }
        }
    };
    public scrollTotop() {
        this.scrollView.scrollToOffset(cc.v2(0, 0), 0);
    };
    public scrollToOffset(e) {
        this.scrollView.scrollToOffset(e, .1);
    };
    public getItemByIndex(e) {
        if (this.itemBuffer) return (this.itemBuffer.find(function (t) {
            return t.index == e;
        }) || {}).item;
    };
    public removeItemByIndex(e) {
        if (this.itemBuffer) {
            var t = this.itemBuffer.findIndex(function (t) {
                return t.index == e;
            });
            if (t >= 0) {
                var a = this.itemBuffer.splice(t, 1);
                this.destroyNode(a.item);
            }
        }
    };
    public bindItemWithIndex(e, t, a) {
        if (this.itemBuffer) {
            a = a || true;
            var o = this.itemBuffer.find(function (t) {
                return t.item == e;
            });
            if (o) {
                o.bindIndex = t;
                if (a) this.bindIndexList[t] = a; else {
                    delete this.bindIndexList[t];
                    delete o.bindIndex;
                }
            }
        }
    };
    public onItemChanged(e) {
        "function" == typeof e && this.callbackList.push(e);
    };
    public runItemChangedCallback(e, t) {
        try {
            for (var a = 0; a < this.callbackList.length; a++) this.callbackList[a](e, t);
        } catch (e) {
            console.error(e);
        }
    };
    public recycle() {
        var e = this;
        this.itemBuffer && this.itemBuffer.forEach(function (t) {
            if (t && cc.isValid(t.item)) {
                t.item.off(cc.Node.EventType.SIZE_CHANGED, e.onItemSizeChanged.bind(e, t.item), e);
                t.item.off(cc.Node.EventType.SCALE_CHANGED, e.onItemSizeChanged.bind(e, t.item), e);
                n.putNode(e.itemName, t.item);
            }
        });
        this.itemCache = null;
        this.itemBuffer = null;
    };
    public getScript(e) {
        if (!e) return null;
        for (var t = e._components, a = 0; a < t.length; a++) if (t[a] && t[a].hasOwnProperty("_super")) return t[a];
        return null;
    };
    public destroyNode(e) {
        if (cc.isValid(e)) {
            e.removeFromParent(false);
            e.destroy();
        } else console.error("Tools: destroyNode error, param is invalid");
    };

}